﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved All Rights Reserved All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Concurrent;
using System.Text;
using FinPlusInterfaces;
using FinPlusAssembler;

namespace FinPlusConnData
{
    public class FinPlusServiceConn : IServiceConn
    {
        private static ConcurrentDictionary<string, ServiceConn> _serviceConns = new ConcurrentDictionary<string, ServiceConn>();

        private static volatile ServiceConn _serviceManager;
        private static volatile object _object = new object();

        //construct
        public FinPlusServiceConn()
        {
            if (_serviceManager == null)
                lock (_object)
                    if (_serviceManager == null)
                        _serviceManager = new ServiceConn();
        }

        //public
        public void Connect(Env env, string config, string user, string serviceKey, string serviceType, string query, bool isTransposed = true, bool isAsync = false)
        {
            try
            {
                ServiceConn serviceConn;
                lock (_serviceConns)
                {
                    if (_serviceConns.ContainsKey(serviceKey)) 
                        return;
                    _serviceConns.TryAdd(serviceKey,  serviceConn = new ServiceConn(env, config, user, serviceKey, serviceType, query, isTransposed, isAsync));
                }
                serviceConn.Start();
            }
            catch (ServiceConnException e)
            {
                Level.Error.Log(string.Format("Failed to connect serviceType={0}, serviceKey={1}, params={2}", serviceType, serviceKey, query), e);
                throw e;
            }
        }

        public void Save(string serviceKey, IPod pod)
        {
            try
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                    serviceConn.Save(pod, ChangeType.New);
            }
            catch (ServiceConnException e)
            {
                Level.Error.Log(string.Format("Failed to save: serviceKey={0} pod {1}", serviceKey, pod.ToString()), e);
            }
        }

        public void Dispose(string serviceKey)
        {
            ServiceConn serviceConn;
            if (_serviceConns.TryRemove(serviceKey, out serviceConn))
                serviceConn.Dispose();
        }

        public string Key(string serviceName, string query, string KeyFormat)
        {
            if(KeyFormat == string.Empty)
                return serviceName;

            var key =  new StringBuilder();
            var p = query.ToDict(true, ';', ',');
          
            foreach (var KeyItem in KeyFormat.ToArray1d(','))
                if (p.ContainsKey(KeyItem.ToString()))
                    key.Append("|" + p[KeyItem.ToString()]);
                else
                    key.Append("|" + KeyItem.ToString());

            return string.Format("{0} {1}", serviceName, string.IsNullOrEmpty(key.ToString()) ? KeyFormat : key.ToString());
        }

        public IDPods GetDPods(string serviceKey)
        {
            try
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                    return serviceConn.DPods;
            }
            catch (ServiceConnException e)
            {
                Level.Error.Log(string.Format("Failed to get: serviceKey={0}", serviceKey), e);
            }
            return null;
        }

        public IPods GetPods(string serviceKey)
        {
            try
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                    return serviceConn.Pods;
            }
            catch (ServiceConnException e)
            {
                Level.Error.Log(string.Format("Failed to get: serviceKey={0}", serviceKey), e);
            }
            return null;
        }

        public IPods Infos() {return _serviceManager.Infos();}

        public bool Stop(string serviceKey){return _serviceManager.Stop(serviceKey);}

        public bool Start(string serviceKey){return _serviceManager.Start(serviceKey);}

        public bool HasCompleted(string serviceKey)
        {
            try
            {
                ServiceConn serviceConn;
                if (_serviceConns.TryGetValue(serviceKey, out serviceConn))
                    return _serviceConns[serviceKey].HasCompleted;
            }
            catch (ServiceConnException e)
            {
                Level.Error.Log(string.Format("Failed to get: serviceKey={0}", serviceKey), e);
            }
            return true;
        }
    }
}

